<?php
/**
 * Created by PhpStorm.
 * User: figo-009
 * Date: 2017/5/23
 * Time: 10:40:41
 */
namespace ApigilityGroup\Service;

use ApigilityUser\DoctrineEntity\User;
use Zend\ServiceManager\ServiceManager;
use Zend\Hydrator\ClassMethods as ClassMethodsHydrator;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrineToolPaginator;
use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator as DoctrinePaginatorAdapter;
use ApigilityGroup\DoctrineEntity;
use ApigilityAddress\DoctrineEntity\Region;

class SettingService
{
    protected $classMethodsHydrator;

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;

    /**
     * @var RegionService
     */
    protected $regionService;

    /**
     * @var UserService
     */
    protected $userService;

    public function __construct(ServiceManager $services)
    {
        $this->classMethodsHydrator = new ClassMethodsHydrator();
        $this->em = $services->get('Doctrine\ORM\EntityManager');
        $this->regionService = $services->get('ApigilityAddress\Service\RegionService');
        $this->userService = $services->get('ApigilityUser\Service\UserService');
    }

    /**
     * 创建一个团购活动
     *
     * @param $data
     * @return DoctrineEntity\GroupSetting
     */
    public function createGroupSetting($data)
    {
        $setting = new DoctrineEntity\Setting();

        $groups = $this->em->getRepository('ApigilityGroup\DoctrineEntity\Setting')
            ->findBy([
            'province' => $data->province,
            'city' => $data->city,
            'district' => $data->district,
        ]);
        if (count($groups)) {
            throw new \Exception('一个地区只能设定一个拼团活动', 404);
        }
        
        if (isset($data->province)) $setting->setProvince($this->regionService->getRegion($data->province));
        if (isset($data->city)) $setting->setCity($this->regionService->getRegion($data->city));
        if (isset($data->district)) $setting->setDistrict($this->regionService->getRegion($data->district));
        if (isset($data->male_free)) {
            $setting->setMaleFreeNums($data->male_free);
            $setting->setMaleFreeLeftNums($data->male_free);
        }
        if (isset($data->female_free)) {
            $setting->setFemaleFreeNums($data->female_free);
            $setting->setFemaleFreeLeftNums($data->female_free);
        }
        if (isset($data->being_group)) $setting->setBeingGroupNums($data->being_group);
        if (isset($data->price)) $setting->setPrice($data->price);
        $setting->setCreatime(new \DateTime());

        $name = $this->regionService->getRegion($data->province)->getName() . '/' .
            $this->regionService->getRegion($data->city)->getName() . '/' .
            $this->regionService->getRegion($data->district)->getName();
        $setting->setName($name);

        $this->em->persist($setting);
        $this->em->flush();

        return $setting;
    }

    /**
     * 修改地址
     *
     * @param $group_setting_id
     * @param $data
     * @return DoctrineEntity\Setting
     * @throws \Exception
     */
    public function updateGroupSetting($group_setting_id, $data)
    {
        $setting = $this->getGroupSetting($group_setting_id);

        if (isset($data->province)) $setting->setProvince($this->regionService->getRegion($data->province));
        if (isset($data->city)) $setting->setCity($this->regionService->getRegion($data->city));
        if (isset($data->district)) $setting->setDistrict($this->regionService->getRegion($data->district));
        if (isset($data->male_free)) {
            $nums = $setting->getMaleFreeLeftNums() + ($data->male_free - $setting->getMaleFreeNums());
            if ($nums < 0) {
                throw new \Exception('已使用的男免费名额超过本次变动数', 404);
            }
            $setting->setMaleFreeLeftNums($nums);
            $setting->setMaleFreeNums($data->male_free);
        }
        if (isset($data->female_free)) {
            $nums = $setting->getFemaleFreeLeftNums() + ($data->female_free - $setting->getFemaleFreeNums());
            if ($nums < 0) {
                throw new \Exception('已使用的女免费名额超过本次变动数', 404);
            }
            $setting->setFemaleFreeLeftNums($nums);
            $setting->setFemaleFreeNums($data->female_free);
        }
        if (isset($data->being_group)) $setting->setBeingGroupNums($data->being_group);
        if (isset($data->price)) $setting->setPrice($data->price);
        if (isset($data->name)) $setting->setName($data->name);

        $this->em->flush();

        return $setting;
    }

    /**
     * 获取一个拼团活动
     *
     * @param $group_setting_id
     * @return DoctrineEntity\Setting
     * @throws \Exception
     */
    public function getGroupSetting($group_setting_id)
    {
        $setting = $this->em->find('ApigilityGroup\DoctrineEntity\Setting', $group_setting_id);

        if (empty($setting)) {
            throw new \Exception('拼团活动不存在', 404);
        } else {
            return $setting;
        }
    }

    /**
     * 获取一个拼团活动
     *
     * @param $group_setting_id
     * @return DoctrineEntity\Setting
     * @throws \Exception
     */
    public function getGroupSettingByAddress($province, $city, $district)
    {
        $groups = $this->em->getRepository('ApigilityGroup\DoctrineEntity\Setting')
            ->findBy([
            'province' => $province,
            'city' => $city,
            'district' => $district,
        ]);

        if (count($groups)) {
            return $groups;
        } else {
            throw new \Exception('户籍所在地区无拼团活动', 404);
        }
    }

    /**
     * 获取用户所在地区的拼团活动
     *
     * @param $user
     * @return DoctrineEntity\Setting
     * @throws \Exception
     */
    public function getGroupSettingByUser(User $user)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('g')->from('ApigilityGroup\DoctrineEntity\Setting', 'g');

        $where = '';

        $qb->innerJoin('g.province', 'gp');
        if (!empty($where)) $where .= ' AND ';
        $where .= 'gp.id = :province_region_id';

        $qb->innerJoin('g.city', 'gc');
        if (!empty($where)) $where .= ' AND ';
        $where .= 'gc.id = :city_region_id';

        $qb->innerJoin('g.district', 'gd');
        if (!empty($where)) $where .= ' AND ';
        $where .= 'gd.id = :district_region_id';

        $personal_certification = $user->getPersonalCertification();
        $region_city = null;
        $region_district = null;
        $region_province = null;
        if(count($personal_certification)){
            $id_card_number = $personal_certification->getIdentityCardNumber();
            $region_code = substr($id_card_number, 0, 6);
            $region_district = $this->regionService->getRegionByCode($region_code, 'district');
        }

        if ($region_district instanceof Region) $region_city = $region_district->getParent();
        if ($region_city instanceof Region) $region_province = $region_city->getParent();

        $qb->where($where);
        $qb->setParameter('province_region_id', $region_province ? $region_province->getId() : '');
        $qb->setParameter('city_region_id', $region_city ? $region_city->getId() : '');
        $qb->setParameter('district_region_id', $region_district ? $region_district->getId() : '');
        $doctrine_paginator = new DoctrineToolPaginator($qb->getQuery());
        return new DoctrinePaginatorAdapter($doctrine_paginator);
    }

    /**
     * 获取拼团活动列表
     *
     * @param $params
     * @return DoctrinePaginatorAdapter
     */
    public function getGroupSettings($params)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('g')->from('ApigilityGroup\DoctrineEntity\Setting', 'g');

        $where = '';

        if (isset($params->province_region_id)) {
            $qb->innerJoin('g.province', 'gp');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'gp.id = :province_region_id';
        }

        if (isset($params->city_region_id)) {
            $qb->innerJoin('g.city', 'gc');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'gc.id = :city_region_id';
        }

        if (isset($params->district_region_id)) {
            $qb->innerJoin('g.district', 'gd');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'gd.id = :district_region_id';
        }

        if(isset($params->user_id)) {
            $user = $this->userService->getUser($params->user_id);
            return $this->getGroupSettingByUser($user);
        }

        if (!empty($where)) {
            $qb->where($where);
            if (isset($params->province_region_id)) $qb->setParameter('province_region_id', $params->province_region_id);
            if (isset($params->city_region_id)) $qb->setParameter('city_region_id', $params->city_region_id);
            if (isset($params->district_region_id)) $qb->setParameter('district_region_id', $params->district_region_id);
        }

        $qb->orderBy('g.id', 'desc');

        $doctrine_paginator = new DoctrineToolPaginator($qb->getQuery());
        return new DoctrinePaginatorAdapter($doctrine_paginator);
    }

    /**
     * 删除一个拼团活动
     *
     * @param $group_setting_id
     * @return bool
     * @throws \Exception
     */
    public function deleteGroupSetting($group_setting_id)
    {
        $setting = $this->getGroupSetting($group_setting_id);

        $this->em->remove($setting);
        $this->em->flush();

        return true;
    }

    public function getGroupTotals($params)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('g.id')->from('ApigilityGroup\DoctrineEntity\Setting', 'g');

        $where = '';

        if (isset($params->province_region_id)) {
            $qb->innerJoin('g.province', 'gp');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'gp.id = :province_region_id';
        }

        if (isset($params->city_region_id)) {
            $qb->innerJoin('g.city', 'gc');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'gc.id = :city_region_id';
        }

        if (isset($params->district_region_id)) {
            $qb->innerJoin('g.district', 'gd');
            if (!empty($where)) $where .= ' AND ';
            $where .= 'gd.id = :district_region_id';
        }

        if(isset($params->user_id)) {
            $user = $this->userService->getUser($params->user_id);
            return $this->getGroupSettingByUser($user);
        }

        if (!empty($where)) {
            $qb->where($where);
            if (isset($params->province_region_id)) $qb->setParameter('province_region_id', $params->province_region_id);
            if (isset($params->city_region_id)) $qb->setParameter('city_region_id', $params->city_region_id);
            if (isset($params->district_region_id)) $qb->setParameter('district_region_id', $params->district_region_id);
        }

        $qb->orderBy('g.id', 'desc');

        $setting = $qb->getQuery()->getArrayResult();
        $setting_ids = array();
        foreach($setting as $s){
            $setting_ids[] = $s['id'];
        }
        $setting_ids = join(',',$setting_ids);
        $totals = array();
        $male_free_participation_totals = $this->getFreeParticipationTotals($setting_ids,1)['total'];
        $female_free_participation_totals = $this->getFreeParticipationTotals($setting_ids,2)['total'];
        $male_participation_totals = $this->getParticipationTotals($setting_ids,1)['total'] - $male_free_participation_totals;
        $female_participation_totals = $this->getParticipationTotals($setting_ids,2)['total'] - $female_free_participation_totals;
        $total = array();
        $total['male_free_participation_totals'] = $male_free_participation_totals;
        $total['female_free_participation_totals'] = $female_free_participation_totals;
        $total['free_articipation_totals'] = $male_free_participation_totals + $female_free_participation_totals;
        $total['male_participation_totals'] = $male_participation_totals;
        $total['female_participation_totals'] = $female_participation_totals;
        $total['participation_totals'] = $male_participation_totals + $female_participation_totals;
        $totals[] = $total;
        return $totals;
    }

    /**
     * 统计免费拼团人数
     * @param $setting_id
     * @param $sex
     * @return \ApigilityOrder\DoctrineEntity\Order
     * @throws \Exception
     */
    public function getFreeParticipationTotals($setting_ids,$sex = '')
    {
        if($sex == 1){
            $count = 'sum(COALESCE(g.male_free_participation_nums,0)) as total';
        }else if($sex == 2){
            $count = 'sum(COALESCE(g.female_free_participation_nums, 0)) as total';
        }else{
            $count = 'sum(COALESCE(g.male_free_participation_nums, 0) + COALESCE(g.female_free_participation_nums, 0)) as total';
        }

        $qb = new QueryBuilder($this->em);
        $qb->select($count)
            ->from('ApigilityGroup\DoctrineEntity\Group', 'g')
            ->where("g.group_setting in ($setting_ids)");
        $total = $qb->getQuery()->getResult();
        if(count($total)){
            return $total[0];
        } else {
            return $this::NO_PARTICIPATION;
        }
    }

    /**
     * 统计付费总拼团人数
     * @param $setting_id
     * @param $sex
     * @return \ApigilityOrder\DoctrineEntity\Order
     * @throws \Exception
     */
    public function getParticipationTotals($setting_ids,$sex = '')
    {
        if($sex == 1){
            $count = 'sum(COALESCE(g.male_participation_nums,0)) as total';
        }else if($sex == 2){
            $count = 'sum(COALESCE(g.female_participation_nums, 0)) as total';
        }else{
            $count = 'sum(COALESCE(g.male_participation_nums, 0) + COALESCE(g.female_participation_nums, 0)) as total';
        }

        $qb = new QueryBuilder($this->em);
        $qb->select($count)
            ->from('ApigilityGroup\DoctrineEntity\Group', 'g')
            ->where("g.group_setting in ($setting_ids)");
        $total = $qb->getQuery()->getResult();
        if(count($total)){
            return $total[0];
        } else {
            return $this::NO_PARTICIPATION;
        }
    }
}